#include "UnitTest.h"
#include "Assertions.h"
#include "Console.h"

namespace CEngine {

namespace UnitTestNothingToSeeHere {
    const U8 MAX_GROUPS = 255;
    const U32 MAX_TESTS = 1024;
}

using namespace UnitTestNothingToSeeHere;

UnitTest::UnitTest(void)
    :   stack(32000),
        groupName(NULL),
        tests(NULL),
        testCount(0),
        groupCount(0)
{
    groupName = (CHAR**)stack.alloc(MAX_GROUPS * sizeof(CHAR*));
    tests = (Test*)stack.alloc(MAX_TESTS * sizeof(Test));

    for (U8 i = 0; i < MAX_GROUPS; ++i) {
        groupName[i] = 0;
    }

    for (U32 i = 0; i < MAX_TESTS; ++i) {
        tests[i].testName = NULL;
        tests[i].groupID = 0;
        tests[i].passed = false;
    }
}

UnitTest::~UnitTest(void) {}

U8
UnitTest::createTestGroup(const CHAR* name) {
    ASSERT(groupCount <= MAX_GROUPS);

    U32 length = 1;

    for (U32 i = 0; name[i] != '\0'; ++i) {
        ++length;
    }

    groupName[groupCount] = (CHAR*)stack.alloc(length);

    CHAR* address = (CHAR*)groupName[groupCount];
    for (U32 i = 0; i < length; ++i) {
        address[i] = name[i];
    }

    return groupCount++;
}

void
UnitTest::printResults(void) const {
    for (U8 i = 0; i < groupCount; ++i) {
        U32 totalTests = 0;
        U32 passedTests = 0;

        for (U32 c = 0; c < testCount; ++c) {
            if(tests[c].groupID == i) {
                ++totalTests;
                if(tests[c].passed)
                    ++passedTests;
            }
        }
        if(totalTests == passedTests) {
            Console::print("%q%s: %d of %d tests passed!\n%r", Console::LGREEN, groupName[i], passedTests, totalTests);
        }
        else if(passedTests > 0){
            Console::print("%q%s: %d of %d tests passed!\n%r", Console::LYELLOW, groupName[i], passedTests, totalTests);
        }
        else {
            Console::print("%q%s: %d of %d tests passed!\n%r", Console::LRED, groupName[i], passedTests, totalTests);
        }

        for (U32 c = 0; c < testCount; ++c) {
            if(tests[c].groupID == i) {
                if(tests[c].passed)
                    Console::print("%q\t%s: PASSED\n%r", Console::LGREEN, tests[c].testName);
                else
                    Console::print("%q\t%s: FAILED\n%r", Console::LRED, tests[c].testName);
            }
        }
    }
}

}
